package com.tomica.mailsigner.signmail;

import java.util.Arrays;
import java.util.List;

import cfca.mobile.keydevice.AudioToken;

import com.Wsdl2Code.WebServices.SignService.VectorString;
import com.entersafe.safeca.Constant;
import com.entersafe.safeca.MyProgressDialog;
import com.entersafe.safeca.P11Other;
import com.tomica.mailsigner.R;
import com.tomica.mailsigner.common.SettingsActivity;
import com.tomica.mailsigner.token.Token;

import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.util.Base64;
import android.util.Log;
import android.util.Patterns;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Activity to create and sign mail then send.
 * Not completed yet.
 * @author TOMICALAB
 *
 */
public class SignMailActivity extends Activity {

	public SignMailModel mModel=null;
	public TextView emailFrom;
	public EditText emailTo;
	public EditText emailCc;
	public EditText emailSubject;
	public EditText emailContent;
	public Button btnChangeSettings;
	public Handler handler;
	private Token token;
	private String randomString;
	
	private BroadcastReceiver headSetReceiver = null;

	private Context context;
	public Resources res;
	public MyProgressDialog progressDialog;
	private String pin;

	@SuppressLint("HandlerLeak")
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		context = this;
		res = getResources();
		
		P11Other.audioToken = new AudioToken(this);

		setContentView(R.layout.activity_email_sign);

		emailFrom = (TextView) findViewById(R.id.tvFromEmail);
		emailTo = (EditText) findViewById(R.id.etTo);
		emailCc = (EditText) findViewById(R.id.etCc);
		emailSubject = (EditText) findViewById(R.id.etSubject);
		emailContent = (EditText) findViewById(R.id.etMailContent);
		
		btnChangeSettings = (Button) findViewById(R.id.btnChangeSettings);
		btnChangeSettings.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// Account setting
				Intent intent = new Intent(context, SettingsActivity.class);
				startActivity(intent);
			}
		});
		
		progressDialog = new MyProgressDialog(this);

		handler = new Handler(){
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case Constant.BUILD_MAIL_OK:
					// After build mail successful from web service, get the return
					// data to sign on token.
					
					// Call to sign PKCS11
					// Get data from server response:
					//result !=null se co 2 phan tu
                    //result[0]: chua chuoi random dinh danh cho giao dich
                    //result[1]: du lieu server tra ve dang base64,  client can ky len du lieu nay
					VectorString vectorResult = (VectorString) msg.obj;
					randomString = (String) vectorResult.getProperty(0);
					String serverDataBase64 = (String) vectorResult.getProperty(1);
					byte[] byteData  = Base64.decode(serverDataBase64, Base64.DEFAULT);
					mModel.signObjectVectorByte(byteData, pin);
					
					break;
				case Constant.GET_PASSWORD:
					progressDialog.setShowInfo(getResources().getString(R.string.inform_sign_onprogress));
					progressDialog.show();
					emailContent = (EditText) findViewById(R.id.etMailContent);
					mModel.startSending(emailContent.getText().toString());
					
					break;
				case Constant.WRONG_PASSWORD:
					// Wrong password, user have to re-enter.
					showDialog(Constant.DIALOG_PASSWORD);
					break;
				case Constant.MAIL_SIGNED_PKCS_OK:
					// After sign data successful on token, we are ready to send
					// mail by web service.
					emailFrom = (TextView) findViewById(R.id.tvFromEmail);
					emailTo = (EditText) findViewById(R.id.etTo);
					emailCc = (EditText) findViewById(R.id.etCc);
					emailSubject = (EditText) findViewById(R.id.etSubject);
					emailContent = (EditText) findViewById(R.id.etMailContent);
					
					VectorString toAddList = getEmailVector(emailTo.getText().toString());
					VectorString toCcList = getEmailVector(emailCc.getText().toString());					
					String subject = emailSubject.getText().toString();
					mModel.sendMailEx((String) msg.obj, toAddList, toCcList,
							subject, pin, randomString);
					break;
				case Constant.SEND_MAIL_EX_OK:
					// Sending mail successful. Showing for user:
					progressDialog.dismiss();
					CharSequence text = context
					.getString(R.string.msg_send_successful);
					int duration = Toast.LENGTH_LONG;
					Toast toast = Toast.makeText(context, text, duration);
					toast.show();
					Log.d("Sendmai", "Complete");
					break;
				case Constant.SERVICE_EXCEPTION:
					// Error when interacting with web service. Display error message. 
					progressDialog.dismiss();
					String message = getResources().getString(R.string.inform_error_internal_server);
					showMessage(message);
					break;
				case Constant.BUILD_MAIL_FAIL:
					// Error when build mail with web service. Display error message. 
					progressDialog.dismiss();
					String buildMessage = getResources().getString(R.string.inform_error_internal_server);
					showMessage(buildMessage);
					break;
				case Constant.MAIL_SIGNED_PKCS_FAIL:
					// Error with token. Display error message.
					progressDialog.dismiss();
					String tokenErr = getResources().getString(R.string.inform_error_token);
					showMessage(tokenErr);
					break;
				case Constant.SEND_MAIL_EX_FAIL:
					// Error when send mail to web service. Display error message. 
					progressDialog.dismiss();
					String sendMessage = getResources().getString(R.string.inform_error_internal_server);
					showMessage(sendMessage);
					break;
				case Constant.SHOWPROGRESSDIALOG:
					Log.e(Constant.Debug, "Dialog of connecting token");
					progressDialog.setShowInfo(res.getString(R.string.inform_tryconnect_init));
					progressDialog.show();
					super.handleMessage(msg);
					break;
				case Constant.CLOSEPROGRESSDIALOG:
					progressDialog.dismiss();
					super.handleMessage(msg);
					break;
				case Constant.SHOWERRINFO:
					if (null != msg.obj) {
						if (msg.obj.toString().compareTo(
								res.getString(R.string.inform_handset_connectfail)) == 0) {
							String title, button;
							button = res.getString(R.string.inform_button_OK);
							title = res.getString(R.string.inform_title);
							new Builder(context)
									.setTitle(title)
									.setMessage(msg.obj.toString())
									.setPositiveButton(button,
											new DialogInterface.OnClickListener() {

												@Override
												public void onClick(
														DialogInterface arg0,
														int arg1) {
													finish();
												}
											}).show();
						} else
							showMessage(msg.obj.toString());
					}
					super.handleMessage(msg);
					break;
				case Constant.TOKEN_CONNECT_OK:
					// Show Toast inform that token connect successfully.
					CharSequence textOK = context.getString(R.string.inform_token_connect_ok);
					Toast toastOk = Toast.makeText(context, textOK, Toast.LENGTH_SHORT);
					toastOk.show();
					break;
				default:
					super.handleMessage(msg);
				}
			}
		};
		
		token = new Token(context, handler);
		
		// Register listening to audiopass
		headSetReceiver = new BroadcastReceiver() {
			public void onReceive(Context context, Intent intent) {
				String action = intent.getAction();
				if (action.equals(Intent.ACTION_HEADSET_PLUG)) {
					// headphone plugged
					if (intent.getIntExtra("state", 0) == 1) {
						Log.i("Handset", "Handset plugin");
						token.tryConnect();

						// headphone unplugged
					} else {
						Log.i("Handset", "Handset plugout");
						token.disConnect();
						// TODO: show dialog to insert AudioPass showDialog(0);

					}
				}
			}
		};
		registerReceiver(headSetReceiver, new IntentFilter(
				Intent.ACTION_HEADSET_PLUG));

	}

	@Override
	protected void onResume() {
		super.onResume();
		if(mModel==null){ 
			mModel = SignMailModel.getInstance(this, handler);
		}
		
		emailFrom.setText(mModel.getEmailAccount());
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.email_sign, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.action_send:
			// Check for network connection first:
			if (isOnline()){
				String error = validate();
				if (error.length() != 0) {
					showErrorDialog(error);
				} else {
					showDialog(Constant.DIALOG_PASSWORD);
				}
			} else {
				// Not online, remind user to check connection
				String message = getResources().getString(R.string.inform_turnon_network);
				showMessage(message);
			}
			return true;
		case R.id.action_settings:
			// Account setting
			Intent intent = new Intent(this, SettingsActivity.class);
			startActivity(intent);
		default:
			return super.onOptionsItemSelected(item);
		}
	}
	
	@Override
	protected void onDestroy() {
		super.onDestroy();
		Log.i(Constant.Debug, "onDestroy Email sign screen");
		// disConnect();
		P11Other.audioToken.Release();
		unregisterReceiver(headSetReceiver);
	}
	
	@SuppressWarnings("deprecation")
	@Override
	public Dialog onCreateDialog(int id) {
		switch (id){
		case Constant.DIALOG_PASSWORD:
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			// Get the layout inflater
			LayoutInflater inflater = this.getLayoutInflater();
			View promptView = inflater.inflate(R.layout.dialog_password, null);
			
			final EditText input = (EditText) promptView.findViewById(R.id.edtInputPass);

			// Inflate and set the layout for the dialog
			// Pass null as the parent view because its going in the dialog layout
			builder.setView(promptView)
			// Add action buttons
			.setPositiveButton(R.string.txt_ok, new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int id) {
					// Continue signing
					pin = input.getText().toString();
					
					Message msg = new Message();
			        msg.what = Constant.GET_PASSWORD;
			        handler.sendMessage(msg);
				}
			})
			.setNegativeButton(R.string.txt_cancel, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int id) {
					// Do nothing.
				}
			});      
			return builder.create();
		default:
			return super.onCreateDialog(0);
		}
	}

	private void showErrorDialog(String error) {
		AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
		alertDialogBuilder.setMessage(error).setPositiveButton(
				this.getString(R.string.txt_ok),
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.cancel();
					}
				});
		AlertDialog alertDialog = alertDialogBuilder.create();
		alertDialog.show();
	}

	/**
	 * Validate user input. Error will return to string to display for user.
	 * @return
	 */
	public String validate() {

		// Validate Email To
		List<String> emailToList = getEmailList(emailTo.getText().toString());
		for (String email : emailToList) {
			if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
				return this.getString(R.string.txt_wrong_email_to) + ": "
						+ email;
			}
		}

		// Validate Email Cc
		List<String> emailCcList = getEmailList(emailCc.getText().toString());
		for (String email : emailCcList) {
			if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()
					&& email.length() != 0) {
				return this.getString(R.string.txt_wrong_email_cc) + ": "
						+ email;
			}
		}
		
		// Validate Subject
		String subject = emailSubject.getText().toString();
		if (subject.length() == 0) {
			return this.getString(R.string.txt_subjec_empty);
		}
		return "";
	}

	public List<String> getEmailList(String emailString) {

		return Arrays.asList(emailString.split("[,\\s]+"));
	}

	public VectorString getEmailVector(String emailString) {
		VectorString vector = new VectorString();
		if (emailString.length() != 0) {
			List<String> emailList = getEmailList(emailString);
			vector.setSize(emailList.size());
			for (int i = 0; i < emailList.size(); i++) {
				vector.set(i, emailList.get(i));
			}
		}
		return vector;
	}

	public boolean isOnline() {
		ConnectivityManager cm =
				(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo netInfo = cm.getActiveNetworkInfo();
		if (netInfo != null && netInfo.isConnectedOrConnecting()) {
			return true;
		}
		return false;
	}
	
	/**
	 * Show dialog for user with content msg
	 * @param msg
	 */
	public void showMessage(String msg) {
		if (null == msg || "" == msg)
			return;
		String title, button;
		button = getResources().getString(R.string.inform_button_OK);
		title = getResources().getString(R.string.inform_title);
		new Builder(this).setTitle(title).setMessage(msg)
				.setPositiveButton(button, null).show();
	}
	
}
